﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CinemaLib;
using OnlineCinemaBooking.BookingService;
using System.Drawing;

namespace OnlineCinemaBooking
{
    public partial class SeatSelection : System.Web.UI.Page
    {
        Reservation reservation;
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                if (Session["ReservationData"] == null || ((Reservation)Session["ReservationData"]).BookedShow.ID != ((Show)Session["ShowData"]).ID)
                {
                    using (BookingService.BookingServiceClient proxy = new BookingServiceClient())
                    {
                        proxy.Open();
                        if (((Reservation)Session["ReservationData"]) != null)
                        {
                            if (((Reservation)Session["ReservationData"]).BookedShow.ID != ((Show)Session["ShowData"]).ID)
                            {
                                proxy.Cancel(((Reservation)Session["ReservationData"]).ID.ToString());
                            }
                        }
                        reservation = proxy.BeginReservation((Show)Session["ShowData"]);
                        Session["ReservationData"] = reservation;
                    }
                }
                reservation = (Reservation)Session["ReservationData"];
                CreateSeatSelection();
                if (Session["Price"] != null)
                {
                    LabelPrice.Text = Session["Price"].ToString();
                }
            }
            catch (HttpException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (InvalidCastException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (System.ServiceModel.FaultException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (System.ServiceModel.CommunicationException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (TimeoutException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (Exception ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
        }

        private void CreateSeatSelection()
        {
            TableSeats.Rows.Clear();
            int i = 0;
            foreach (Row r in reservation.BookedShow.HallRoom.Rows)
            {
                int j = 0;
                TableRow tr = new TableRow();
                tr.BorderStyle = BorderStyle.None;
                tr.BorderWidth = 0;

                foreach (Seat s in r.Seats)
                {
                    TableCell tc = new TableCell();
                    tc.BorderStyle = BorderStyle.None;
                    tc.BorderWidth = 0;
                    tc.Width = 18;
                    tc.Height = 18;
                    tc.BorderWidth = 0;
                    tc.ColumnSpan = 0;
                    ImageButton ib = new ImageButton();
                    ib.Height = 18;
                    ib.Width = 18;
                    ib.ID = s.ID.ToString();
                    ib.Click += new ImageClickEventHandler(Seat_Click);
                    if (s.Occupied)
                    {
                        ib.ImageUrl = "~/Images/Occupied.png";
                    }
                    else if (reservation.Tickets.Any(t => t.Seat.ID == s.ID))
                    {
                        ib.ImageUrl = "~/Images/Choise.png";
                    }
                    else
                    {
                        ib.ImageUrl = "~/Images/Empty.png";
                    }

                    tc.Controls.Add(ib);
                    tr.Cells.Add(tc);
                    j++;
                }
                TableSeats.Rows.Add(tr);
                i++;
            }
        }

        public void FindBestSeats(int amount)
        {
            if (reservation.BookedShow.HallRoom == null)
                return;
            if (amount < reservation.Tickets.Count)
            {
                for (int i = 0; i < reservation.Tickets.Count - amount; i++)
                {
                    reservation.Tickets.RemoveAt(0);
                }
                return;
            }

            int Rows = reservation.BookedShow.HallRoom.Rows.Count - 1;
            int Cols = reservation.BookedShow.HallRoom.Rows.Max(s => s.Seats.Count) - 1;
            Point Center = new Point(Rows / 2, Cols / 2);

            List<Point> bestpoint = new List<Point>();

            for (int r = 0; r < Rows + 1; r++)
            {
                for (int c = 0; c < Cols + 1; c++)
                {
                    if (reservation.Tickets.Any(t => t.Seat.ID == reservation.BookedShow.HallRoom.Rows[r].Seats[c].ID) || reservation.BookedShow.HallRoom.Rows[r].Seats[c].Occupied)
                    {
                        continue;
                    }
                    if (bestpoint.Any(s => Distance(Center, s) >= Distance(Center, new PointF(r, c))) || bestpoint.Count == 0)
                    {
                        bestpoint.Add(new Point(r, c));

                        if (bestpoint.Count > (amount - reservation.Tickets.Count))
                        {
                            bestpoint = bestpoint.OrderByDescending(d => Distance(d, Center)).ToList<Point>();
                            bestpoint.RemoveAt(0);
                        }
                    }
                }
            }
            int a = int.Parse(DropDownListAdult.Text);
            int k = int.Parse(DropDownListKid.Text);
            int st = int.Parse(DropDownListStudent.Text);
            int se = int.Parse(DropDownListSenior.Text);

            foreach (Point p in bestpoint)
            {
                if (a != 0)
                {
                    reservation.Tickets.Add(new Ticket(reservation.BookedShow.HallRoom.Rows[p.X].Seats[p.Y], TicketType.Adult));
                    a--;
                }
                else if (k != 0)
                {
                    reservation.Tickets.Add(new Ticket(reservation.BookedShow.HallRoom.Rows[p.X].Seats[p.Y], TicketType.Child));
                    k--;
                }
                else if (st != 0)
                {
                    reservation.Tickets.Add(new Ticket(reservation.BookedShow.HallRoom.Rows[p.X].Seats[p.Y], TicketType.Student));
                    st--;
                }
                else if (se != 0)
                {
                    reservation.Tickets.Add(new Ticket(reservation.BookedShow.HallRoom.Rows[p.X].Seats[p.Y], TicketType.Senior));
                    se--;
                }
            }
        }

        public static double Distance(PointF p1, PointF p2)
        {
            return Math.Sqrt(Math.Pow((p1.X - p2.X + 2) * 6, 2) + Math.Pow((p1.Y - p2.Y), 2));
        }

        private void Seat_Click(object sender, ImageClickEventArgs e)
        {
            int a = int.Parse(DropDownListAdult.Text);
            int k = int.Parse(DropDownListKid.Text);
            int st = int.Parse(DropDownListStudent.Text);
            int se = int.Parse(DropDownListSenior.Text);
            int limit = a + k + st + se;
            double price = 0;

            foreach (Row r in reservation.BookedShow.HallRoom.Rows)
            {
                foreach (Seat s in r.Seats)
                {
                    if (s.ID.ToString() == (sender as ImageButton).ID)
                    {
                        if (reservation.Tickets.Exists(t => t.Seat.ID.ToString() == (sender as ImageButton).ID))
                        {
                            reservation.Tickets.Remove(reservation.Tickets.First(t => t.Seat.ID.ToString() == (sender as ImageButton).ID));
                        }
                        else
                        {
                            if (reservation.Tickets.Count + 1 > limit && reservation.Tickets.Count != 0)
                            {
                                reservation.Tickets.RemoveAt(0);
                            }
                            if (a != 0)
                            {
                                price += reservation.BookedShow.Price;
                                reservation.Tickets.Add(new Ticket(s, TicketType.Adult));
                                a--;
                            }
                            else if (k != 0)
                            {
                                price += reservation.BookedShow.Price * 0.5;
                                reservation.Tickets.Add(new Ticket(s, TicketType.Child));
                                k--;
                            }
                            else if (st != 0)
                            {
                                price += reservation.BookedShow.Price * 0.75;
                                reservation.Tickets.Add(new Ticket(s, TicketType.Student));
                                st--;
                            }
                            else if (se != 0)
                            {
                                price += reservation.BookedShow.Price * 0.75;
                                reservation.Tickets.Add(new Ticket(s, TicketType.Senior));
                                se--;
                            }
                        }
                        Session["ReservationData"] = reservation;
                        CreateSeatSelection();
                        try
                        {
                            using (BookingService.BookingServiceClient proxy = new BookingServiceClient())
                            {
                                proxy.Open();
                                proxy.UpdateReservation(reservation);
                            }
                            return;
                        }
                        catch (System.ServiceModel.FaultException ex)
                        {
                            Session["Error"] = ex;
                            Response.Redirect("ErrorPage.aspx");
                        }
                        catch (System.ServiceModel.CommunicationException ex)
                        {
                            Session["Error"] = ex;
                            Response.Redirect("ErrorPage.aspx");
                        }
                        catch (TimeoutException ex)
                        {
                            Session["Error"] = ex;
                            Response.Redirect("ErrorPage.aspx");
                        }
                        catch (Exception ex)
                        {
                            Session["Error"] = ex;
                            Response.Redirect("ErrorPage.aspx");
                        }
                    }
                }
            }
            CreateSeatSelection();
        }

        protected void ButtonProceed_Click(object sender, EventArgs e)
        {
            Session["ReservationData"] = reservation;
            Response.Redirect("UserInfo.aspx");
        }

        protected void ButtonBack_Click(object sender, EventArgs e)
        {
            try
            {
                using (BookingService.BookingServiceClient proxy = new BookingServiceClient())
                {
                    proxy.Open();
                    proxy.Cancel(((Reservation)Session["ReservationData"]).ID.ToString());
                }
                Session.Abandon();
                Response.Redirect("Default.aspx");
            }
            catch (HttpException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (InvalidCastException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (System.ServiceModel.FaultException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (System.ServiceModel.CommunicationException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (TimeoutException ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
            catch (Exception ex)
            {
                Session["Error"] = ex;
                Response.Redirect("ErrorPage.aspx");
            }
        }

        protected void DropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            LabelPrice.Text = ((int.Parse(DropDownListAdult.Text) * reservation.BookedShow.Price) + (int.Parse(DropDownListKid.Text) * (reservation.BookedShow.Price * 0.5)) + (int.Parse(DropDownListStudent.Text) * (reservation.BookedShow.Price * 0.75)) + (int.Parse(DropDownListSenior.Text) * (reservation.BookedShow.Price * 0.75))).ToString();
            FindBestSeats(int.Parse(DropDownListAdult.Text) + int.Parse(DropDownListKid.Text) + int.Parse(DropDownListStudent.Text) + int.Parse(DropDownListSenior.Text));
            Session["ReservationData"] = reservation;
            CreateSeatSelection();
        }
    }
}